Import mojo.app

Import mojo.graphics
Import mojo.input
Import mojo.audio
Import tween2
Import diddy
Import model
Import numberButtonsBonus1
'
' NumberApp 
'
' Used for delta timing movement
Global dt:DeltaTimer
Global LilGuyList:List<LilGuy> = New List<LilGuy>
Global ScoreBubbleList:List<ScoreBubble> = New List<ScoreBubble>
Global PLAYING_AREA_HEIGHT:Int
Global PLAYING_AREA_WIDTH:Int

	Const ADD_MODE = 0
	Const SUBTRACT_MODE = 1
	Const MULTIPLY_MODE = 2
	Const DIVIDE_MODE = 3
	Const MIX_MODE = 4
	
	Const START_GAME_STATE = 0
	Const BETWEEN_LEVEL_STATE = 1
	Const PLAYING_GAME_STATE = 2
	Const GAME_OVER_STATE = 3 
	
	Const GRAVITY:Float = 0.3

Class BonusScreen Extends Screen
	Field baddyNumber1:BaddyNumber
	Field baddyNumber2:BaddyNumber
	Field baddyNumber3:BaddySign
	Field bulletNumber1:Bullet
	Field bulletNumber2:Bullet
	Field bulletNumber3:Bullet
	Field player:PlayerBonus

	Field text:String="INPUT:"
	Field score:Int=0
	Field modeSymbol:String = "+"
	
	Field collisionWidth = 66
	Field collisionHeight = 49
	Field gameOver:Bool = False
	Field fart1:Sound
	Field fart2:Sound
	Field spark:GameImage
	Field FPS% = 60
	Field level:BonusLevel
	Field ballonsThisLevel:Int = 0

	Field currentState:Int = START_GAME_STATE
	Field betweenLevelTimer:Int
	
	Field gameMode:Int
	
	Field levelComplete:bool = false
	
	Field numberButton: NumberButtonsBonus1
	
	Method New(_level:BonusLevel)
		name = "Bonus"
		
		' Store the device width and height
	
        PLAYING_AREA_HEIGHT =   SCREEN_HEIGHT-_model.statusPanel.height
		PLAYING_AREA_WIDTH =   SCREEN_WIDTH-150
		SetUpdateRate FPS
		level = _level
		ballonsThisLevel = 0
		
	
		spark = game.images.Find("glow-1")

		player = New PlayerBonus
		numberButton = New NumberButtonsBonus1(0,_model.mapHeight+50, SCREEN_WIDTH,150)
	End
	
	Method Start:Void()

		LilGuyList.Clear
		ScoreBubbleList.Clear
		Particle.Clear
		
		bulletNumber1 = New Bullet
		bulletNumber2 = New Bullet
		bulletNumber3 = New Bullet
	
		Seed = Millisecs()
		' Create the delta timer
		dt = New DeltaTimer(FPS)

		GenerateBaddys()
		
		_model.messageWindow.Show("SOLVE THE SUMS;TO ESCAPE THE;LADYBIRDS" , New StartGameMessageCallback2(self))
    End

    Method OnLoading:Int()
        Return 0
    End

    Method Update:Void()
		Local result:Int
		Local hasInput = False
		_model.messageWindow.Update()
		dt.UpdateDelta()
		numberButton.Update
		
		Select currentState
		Case START_GAME_STATE

		Case BETWEEN_LEVEL_STATE
			player.Update()
		Case PLAYING_GAME_STATE
			baddyNumber1.OnUpdate()
			baddyNumber2.OnUpdate()
			baddyNumber3.OnUpdate()
			bulletNumber1.OnUpdate()
			bulletNumber2.OnUpdate()
			bulletNumber3.OnUpdate()
	
			player.Update()
			
			If KeyHit(KEY_ESCAPE)
				game.screenFade.Start(50, True)
				game.nextScreen = _model._mazeScreen				
			End
			
			Local char=GetChar()
			If(char>=32)
				text=Int(char)-48
				hasInput = True
			Else If (numberButton.inputNumber<>"")
				' get number pressed by mouse:
				text = numberButton.inputNumber
				hasInput = True
				numberButton.Clear()
			EndIf
			
			If (hasInput And gameOver=False)			
				
				Select gameMode
					Case ADD_MODE
						result = baddyNumber1.number+baddyNumber2.number	
					
					Case SUBTRACT_MODE
						result = baddyNumber1.number-baddyNumber2.number	
				End'Select
			
				If Int(text)=result 	
					bulletNumber1.x=player.x
					bulletNumber1.y=player.y
					bulletNumber1.FindPath(baddyNumber1.x, baddyNumber1.y, baddyNumber1.dy+6)
					bulletNumber1.kill=False
					
					bulletNumber2.x=player.x
					bulletNumber2.y=player.y
					bulletNumber2.FindPath(baddyNumber2.x, baddyNumber2.y, baddyNumber2.dy+6)
					bulletNumber2.kill=False
					
					bulletNumber3.x=player.x
					bulletNumber3.y=player.y
					bulletNumber3.FindPath(baddyNumber3.x, baddyNumber3.y, baddyNumber3.dy+6)
					bulletNumber3.kill=False									
				Endif
				
				
			Endif
			
			If (baddyNumber1.kill = True And baddyNumber2.kill = True And baddyNumber3.kill = True)
				score=score+1
				ballonsThisLevel+=1
				
				If(ballonsThisLevel>level.MaxBallonsThisLevel)
					currentState=BETWEEN_LEVEL_STATE
					_model.messageWindow.Show("YOU GOT x STARS", new EndGameMessageCallback2())
				Endif
				GenerateBaddys()
			Endif
			
			If ((baddyNumber1.y> PLAYING_AREA_HEIGHT) And 
			    (baddyNumber2.y> PLAYING_AREA_HEIGHT) And 
			    (baddyNumber3.y> PLAYING_AREA_HEIGHT))
				'GenerateBaddys()
				currentState=GAME_OVER_STATE
				gameOver=True
				_model.bonusGameFailed = true
				_model.bonusGameSuccess=false
				game.screenFade.Start(50, True)
				game.nextScreen = _model._mazeScreen
			Endif
			
				checkCollisions()
				Particle.UpdateAll()
				UpdateLilGuysZ()
				UpdateScoreBubblesZ()
		End
			
    End

    Method Render:Void()
		SetAlpha 1
		Cls 0,200,0
		'DrawImage bg, DeviceWidth/2, PLAYING_AREA_HEIGHT/2, 0	
		
		player.Draw()

		Select currentState			
			Case START_GAME_STATE
				
			Case BETWEEN_LEVEL_STATE

			Case PLAYING_GAME_STATE				
				baddyNumber1.Draw()
				baddyNumber2.Draw()
				baddyNumber3.Draw()

				bulletNumber1.Draw()
				bulletNumber2.Draw()
				bulletNumber3.Draw()

				
				Particle.DrawAll()
						
			Case GAME_OVER_STATE
		
			End
			
			numberButton.Render
			SetAlpha 1
			_model.statusPanel.Draw
			_model.messageWindow.Draw()
			_model.fpsCounter.Draw(0,100)
    End    

	Method GenerateBaddys:Void()
	
		baddyNumber1 = New BaddyNumber(level.startVelocity)
		baddyNumber2 = New BaddyNumber(level.startVelocity)
		baddyNumber3 = New BaddySign(level.startVelocity)

		baddyNumber1.x = Rnd(50, PLAYING_AREA_WIDTH/2-50)
		baddyNumber2.x = Rnd(PLAYING_AREA_WIDTH/2+50, PLAYING_AREA_WIDTH-50)
		baddyNumber3.x = PLAYING_AREA_WIDTH/2

		bulletNumber1.kill=True
		bulletNumber2.kill=True
		bulletNumber3.kill=True
		
		baddyNumber1.kill=False
		baddyNumber2.kill=False
		baddyNumber3.kill=False
		
		baddyNumber1.dy+=level.velocityIncrement
		baddyNumber2.dy+=level.velocityIncrement
		baddyNumber3.dy+=level.velocityIncrement
		
		'too close
		While(Abs(baddyNumber2.x-baddyNumber1.x) <50)
			baddyNumber2.x = Rnd(PLAYING_AREA_WIDTH/2, PLAYING_AREA_WIDTH-50)
		Wend
		
		If(level.mode = MIX_MODE)
			gameMode = Rnd(0,2)
		Else 
			gameMode = level.mode
		Endif

		Select gameMode
			Case ADD_MODE
				baddyNumber1.number=Rnd(1,10)
				baddyNumber2.number=Rnd(10-baddyNumber1.number)
				modeSymbol = "+"
			Case SUBTRACT_MODE
				baddyNumber1.number=Rnd(1,10)
				baddyNumber2.number=Rnd(0, baddyNumber1.number)
				modeSymbol = "-"
		End'Select
		
		baddyNumber3.sign = gameMode
		
	End
	
	Method checkCollisions:Void()
	If(bulletNumber1.kill=False) Then
		If(bulletNumber1.y<baddyNumber1.y+(baddyNumber1.radius/2)) 
			bulletNumber1.kill=True
			baddyNumber1.collision=True
			For Local i% = 1 To 6
					Particle.Create(spark, bulletNumber1.x, bulletNumber1.y, Rnd(-2,2), Rnd(-3,-1), GRAVITY/4, 2000)
			Next
			_model.addStar()
			'ParticleExplosion(bulletNumber1.x, bulletNumber1.y, particle, 30, 100)
		'	Local lilGuy:LilGuy = New LilGuy(bulletNumber1.x, bulletNumber1.y)
		'	PlaySound( fart1, 0, 0)
		Endif
	Endif
	If(bulletNumber2.kill=False) Then
		If(bulletNumber2.y<baddyNumber2.y+(baddyNumber2.radius/2)) 
			bulletNumber2.kill=True
			baddyNumber2.collision=True
			For Local i% = 1 To 6
				Particle.Create(spark, bulletNumber2.x, bulletNumber2.y, Rnd(-2,2), Rnd(-3,-1), GRAVITY/4, 2000)
			Next
		'	Local lilGuy:LilGuy = New LilGuy(bulletNumber2.x, bulletNumber2.y)
		'	PlaySound( fart2, 0, 0)
		Endif
	Endif
	If(bulletNumber3.kill=False) Then
		If(bulletNumber3.y<baddyNumber3.y+(baddyNumber3.radius/2)) 
			bulletNumber3.kill=True
			baddyNumber3.collision=True
			For Local i% = 1 To 6
			Particle.Create(spark, bulletNumber3.x, bulletNumber3.y, Rnd(-2,2), Rnd(-3,-1), GRAVITY/4, 2000)
			Next
			
			'ParticleExplosion(bulletNumber3.x, bulletNumber3.y, particle, 30, 100)
		'	Local lilGuy:LilGuy = New LilGuy(bulletNumber3.x, bulletNumber3.y)
			'PlaySound( fart3, 0, 0)
		Endif
	Endif


	End
	
	
	Function FloatArray2D:Float[][] (X%,Y%)
		Local tmp:Float[X][]
		For Local I% = 0 Until X
			tmp[I] = New Float[Y]
		Next
		Return tmp
	
		'Local tmp := [New Float[X],New Float[Y]]  ' >:-(
	End Function
	
	
End
'
'BaddyNumber
'
Class BaddyNumber Extends Sprite
	Field radius:Float
	Field scaledRadius:Float
	Field kill = False
	Field angle:Float
	Field number:Int
	Field collision:Bool = False
	Field collisionAnimCounter:Int = 20
	
	Method New(startVelocity:Float)
		Super.New(game.images.Find("mapstrip"), Rnd(PLAYING_AREA_WIDTH-50)+50, -50)
		scaleX=2    
		scaleY=2       
		radius = 32
	
		dy = Rnd(startVelocity -0.5,startVelocity )

		collisionAnimCounter=20
		angle=Rnd(50)
		collision=False
		kill=False

    End

	Method OnUpdate:Int()
		If (kill=False)
		
			Move()
			angle = angle+1 * dt.delta

		Endif
		If (collision=True)
	
				collision=False
				kill=True				
		
		Endif
        Return 0 

    End

    Method Draw:Void()
		If (kill=False)
			
			PushMatrix 
			Translate (x, y)
			'Scale (scaleX,scaleY)
			'Rotate(Sin(angle)*20)
			
			'SetColor( 255,0,0 )
			
			DrawImage(image.image, 0 , 0 , 9)
			SetColor( 255,255,255 )
			Translate (-8, -8 )
			_model.font.DrawText(String(number), 0, 0)
			PopMatrix 
		Endif
    End   
End

'
'BaddySign
'
Class BaddySign Extends BaddyNumber

	Field sign:String
	Field modeSymbol:String
	
	Method New(startVelocity:Float)  
		Super.New (startVelocity)
		x = PLAYING_AREA_WIDTH/2
    End

    Method Draw:Void()
		If (kill=False)
			Select sign
				Case ADD_MODE					
					modeSymbol = "+"
					
				Case SUBTRACT_MODE
					modeSymbol = "-"
			End'Select

			PushMatrix 
			Translate (x, y)
		'	Scale (scaleX,scaleY)
		'	Rotate(Sin(angle)*20)
			
			'SetColor( 255,0,0 )
			
			DrawImage(image.image, 0 , 0 , 9)
			SetColor( 255,255,255 )
			Translate (-8, -8 )
			_model.font.DrawText(modeSymbol , 0, 0)
			PopMatrix 
		Endif
    End   
End

Class LilGuy Extends Sprite
	Field destx:Float
	Field desty:Float
	Field pathLen:Int
	Field kill:Bool = False
	Field onGround = False
	Field homeLocation = False
	Field tween:Tween2
	Field fieldNestX:Float
	
	Method New(_x:Float, _y:Float)   
	Super.New(game.images.Find("wheelie4"),_x, _y)
		 LilGuyList.AddLast(Self)
     	fieldNestX = Rnd(40, 70) ' spead the lil guys out in the nest so we can see them
		tween = New Tween2(Tween2.Cubic.EaseInOut,y,DeviceHeight-50,2000)
         tween.Rewind()
         tween.Start() 	
    End

	Method Update:Int()	
		If(kill=False) Then
			tween.Update()
			If(homeLocation = False)			
				If ((y>=PLAYING_AREA_HEIGHT-50) And onGround = False)
					onGround = True
					'change tween for ground anim
					tween.SetValue(x, Rnd(40,50))
					tween.Rewind()
         			tween.Start() 
				Endif
				
				If ((x<=fieldNestX ) And homeLocation = False) Then
					'change tween for nest anim
					tween.SetValue(y, y-30)
					tween.SetEquation(Tween2.Bounce.EaseIn)
					tween.SetDuration(Rnd(1500,2000))
					tween.SetYoYo(True)
					tween.SetLooping(True)
					tween.Rewind()
         				tween.Start() 
					homeLocation=True
					
					' ScoreBubble
					Local scoreBubble:ScoreBubble = New ScoreBubble ()
					scoreBubble.Create(x, y)

				End
			Endif	
			
			If(onGround And homeLocation)
				y = tween.Value()
			Else If (onGround And homeLocation=False)
				x= tween.Value()
			Else If (onGround = False)
				y= tween.Value()
			EndIf
			
		Endif
        Return 0 
    End

   
End

Function UpdateLilGuysZ()	
	For Local UpdateP:LilGuy = Eachin LilGuy.LilGuyList
			UpdateP.Update()
	Next
End Function

Function ClearLilGuysZ()	
	LilGuy.LilGuyList.Clear()
End Function

Function DrawLilGuysZ()	
For Local UpdateP:LilGuy = Eachin LilGuy.LilGuyList
			UpdateP.Draw()
	Next
End Function



Class Bullet Extends Sprite
	Field destx:Float
	Field desty:Float
	Field pathLen:Int
	Field kill:Bool = True
	
	Method New()
	Super.New(game.images.Find("16CircleOrange")   ,0,0)    
		speed=5   	
    End

	Method OnUpdate:Int()	
		If(kill=False) Then
			Move()						
		Endif
        Return 0 
    End

    Method Draw:Void()
		If(kill=False) Then
			Super.Draw(0,0)
		Endif
    End
 
	Method FindPath:Void(baddyX:Int, baddyY:Int, speed:Float)
		'pythagorus
		Local a:Float
		Local b:Float
		Local c:Float
		
		a = baddyX-x
		b = baddyY-y
		
		destx=baddyX
		desty=baddyY
		c = Sqrt(Pow(a,2)+Pow(b,2))
		
		dx= (a/c)*speed
		dy= (b/c)*speed
		
	End
End

Class PlayerBonus Extends Sprite
	Field destx:Float
	Field desty:Float
	Field pathLen:Int
	Field kill:Bool = True

	Method New()
	Super.New(game.images.Find("mapstrip")  ,PLAYING_AREA_WIDTH/2,_model.mapHeight-60 )  
		destx=100
		desty=PLAYING_AREA_HEIGHT-50
		speed=1
		
		FindPath(destx, desty)
		frame=3
    End

	Method Update:Void()	
		UpdateAnimation()
		Move()
		
		If (dx<0 And (x<destx)) Or 
		   (dx>0 And (x>destx))Then
			destx=Rnd(PLAYING_AREA_WIDTH-50)+50
			FindPath(destx, desty)		
		Endif	
		
		If(destx>x)
			scaleX=-1
		Else
			scaleX=1
		Endif
    End

	Method FindPath:Void(baddyX:Int, baddyY:Int)
		'pythagorus
		Local a:Float
		Local b:Float
		Local c:Float
		
		a = baddyX-x
		b = baddyY-y
		
		destx=baddyX
		desty=baddyY
		c = Sqrt(Pow(a,2)+Pow(b,2))
		
		dx= (a/c)*speed
		dy= (b/c)*speed
		
	End


End

' written after drinking whisky, beware
Class ScoreBubble
	Field tween:Tween2
	Field tweenAlpha:Tween2
	Field x:Float
	Field y:Float
	Field destY:Float
	Field score:String = "+1"
	
	Method Create(_x:Int, _y:Int)
		ScoreBubbleList.AddLast(Self)
		x=_x
		y=_y
		destY=y-250
		tween = New Tween2(Tween2.Linear,y,destY,4000)
		tweenAlpha = New Tween2(Tween2.Linear,1,0,4000)

		tween.Start()
		tweenAlpha.Start()
	End
	
	Method Update()
		If (y<=destY)
			'Kill me
			ScoreBubbleList.Remove(Self)
		End
		tween.Update()
		tweenAlpha.Update()
	End
	
	Method Render()
		y = tween.Value()
		PushMatrix
		SetAlpha(tweenAlpha.Value())
		DrawText (score,x,y,  0.5, 0.5)
		
		PopMatrix
	End
End

Function UpdateScoreBubblesZ()	
	For Local UpdateP:ScoreBubble = Eachin ScoreBubble.ScoreBubbleList
			UpdateP.Update()
	Next
End Function

Function ClearScoreBubblesZ()	
	ScoreBubble.ScoreBubbleList.Clear()
End Function

Function DrawScoreBubblesZ()	
For Local UpdateP:ScoreBubble = Eachin ScoreBubble.ScoreBubbleList
			UpdateP.Render()
	Next
End Function


Class NumberButtonsBonus
	Field width = (DeviceWidth()-PLAYING_AREA_WIDTH)/2
	Field height = PLAYING_AREA_HEIGHT/5
	Field highlightNumber = 0
	Field pressedNumber:int = -1
	
	Method Update()
		Local number:Int = 0
		Local mouseY:Float=MouseY()
		Local mouseX:Float=MouseX()
		pressedNumber = -1
		
		If (mouseX>PLAYING_AREA_WIDTH)
			For Local y:Int = 1 To 5
				For Local x:Int = 1 To 2
					number += 1
					if(mouseX>x*width-width+PLAYING_AREA_WIDTH And mouseX<x*width+PLAYING_AREA_WIDTH And mouseY>y*height-height And mouseY< y*height)
						highlightNumber = number
					End
					
				Next
			Next
		Endif
		
		If (MouseHit(MOUSE_LEFT)>0)
			pressedNumber = highlightNumber
			Print(pressedNumber)			
		Else
			pressedNumber = -1
		End
	End
	
	
	Method Render()
		Local number:Int = 0
		PushMatrix		
		For Local y:Int = 1 To 5
		For Local x:Int = 1 To 2
		
		
		number += 1
		
		If(number=highlightNumber)
			SetColor(0,200,0)
		Else
			SetColor(200,0,0)
		endif
		DrawRect(x*width-width+PLAYING_AREA_WIDTH, y*height-height, width, height )
		DrawText(number, x*width-width/2+PLAYING_AREA_WIDTH, y*height-height/2)

		Next
		Next
		PopMatrix
		
	End
	
End

Class BonusLevel
	Field mode:Int = ADD_MODE
	Field MaxBallonsThisLevel:Int
	Field startVelocity:Float
	Field velocityIncrement:Float
	
	Method New(_mode:Int, _MaxBallonsThisLevel:Int, _startVelocity:Float, _velocityIncrement:Float)
		mode = _mode
		MaxBallonsThisLevel = _MaxBallonsThisLevel
		startVelocity = _startVelocity
		velocityIncrement = _velocityIncrement
	End
End

Class EndGameMessageCallback2 Implements WindowCallback

	Method onClose:Void()
		_model.bonusGameSuccess=true
		_model.bonusGameFailed=false
		game.screenFade.Start(50, True)
		game.nextScreen = _model._mazeScreen
	End
End

Class StartGameMessageCallback2 Implements WindowCallback
	Field parent:BonusScreen = null

	Method New(parent:BonusScreen)
		self.parent = parent
	End

	Method onClose:Void()
		parent.currentState=PLAYING_GAME_STATE
	End
End













